﻿
Imports System.Net
Imports std

Public Class storoomTalk2
    Private Class result_t
        Public Delegate Function DATA_DELEGATE(Of T)() As T
        Private _rst As Boolean = False
        Private _d As Object = Nothing

        Public Sub New(ByVal r As Boolean, ByVal d As Object)
            _rst = r
            _d = d
        End Sub

        Public Function result() As Boolean
            Return _rst
        End Function

        Public Function data_object() As Object
            Return _d
        End Function

        Public Function data(Of T)() As T
            Return convertor.cast(Of T)(data_object())
        End Function
    End Class

    Private talk As tcpTalk = Nothing
    Private retrytimes As Int64 = 0
    Private receiveIndex As Int64 = 0
    Private series As vector(Of _do(Of Boolean)) = Nothing
    Private results As vector(Of result_t) = Nothing

    Private Sub _new(ByVal host As String, ByVal port As Int32, _
                     ByVal retrytimes As Int64, ByVal holdtime As Int64, ByVal livetime As Int64)
        Me.retrytimes = max(retrytimes, 1)
        talk = New tcpTalk()
        talk.host = host
        talk.port = port
        talk.holdtime = holdtime
        talk.livetime = livetime
        series = New vector(Of _do(Of Boolean))()
        results = New vector(Of result_t)()
    End Sub

    Public Sub New(ByVal host As String, ByVal port As Int32, _
                   Optional ByVal retrytimes As Int64 = talkTime.client2room.retrytimes, _
                   Optional ByVal holdtime As Int64 = talkTime.client2room.holdtime, _
                   Optional ByVal livetime As Int64 = talkTime.client2room.livetime)
        _new(host, port, retrytimes, holdtime, livetime)
    End Sub

    Public Sub New(ByVal ipaddress As IPEndPoint, _
                   Optional ByVal retrytimes As Int64 = talkTime.client2room.retrytimes, _
                   Optional ByVal holdtime As Int64 = talkTime.client2room.holdtime, _
                   Optional ByVal livetime As Int64 = talkTime.client2room.livetime)
        assert(Not ipaddress Is Nothing)
        _new(Convert.ToString(ipaddress.Address), ipaddress.Port, retrytimes, holdtime, livetime)
    End Sub

    Public Function host() As String
        Return talk.host()
    End Function

    Public Function port() As Int32
        Return talk.port()
    End Function

    Private Delegate Function NT_DELEGATE(Of T)(ByVal index As Int64, ByRef rtn As T) As Boolean

    Private Function _t(Of T)(ByRef rtn As T, ByVal nt As NT_DELEGATE(Of T)) As Boolean
        assert(Not nt Is Nothing)
        If talk.receiveData().fieldCount() <= receiveIndex Then
            Return False
        Else
            Return nt(inc_(receiveIndex), rtn)
        End If
    End Function

    Private Function t(ByRef rtn As bytes) As Boolean
        Return _t(rtn, AddressOf talk.receiveData().take)
    End Function

    Private Function t(ByRef rtn As String) As Boolean
        Return _t(rtn, AddressOf talk.receiveData().take)
    End Function

    Private Function t(ByRef rtn As UInt64) As Boolean
        Dim s As String = Nothing
        Return t(s) AndAlso convertor.touint64(s, rtn)
    End Function

    Private Function suc() As Boolean
        Dim rtn As String = Nothing
        Return t(rtn) AndAlso strsame(rtn, protocol.success, False)
    End Function

    Private Function c(ByVal rtn As _do(Of Boolean), ByVal ParamArray p() As Object) As Boolean
        assert(Not p Is Nothing AndAlso p.Length > 0)
        For i As Int64 = 0 To p.Length() - 1
            If Not talk.sendData.insert(p(i)) Then
                Return False
            End If
        Next
        Return series.push_back(rtn)
    End Function

    Private Function rb(Of T)() As T
        Return results.back().data(Of T)()
    End Function

    Private Function mp(ByVal rst As Boolean, ByVal i As Object) As result_t
        Return New result_t(rst, i)
    End Function

    Private tf_rtn As _do(Of Boolean) = _
        Function() As Boolean
            If suc() Then
                results.push_back(mp(True, True))
            Else
                results.push_back(mp(False, False))
            End If
            Return True
        End Function

    Private uint64_rtn As _do(Of Boolean) = _
        Function() As Boolean
            If suc() Then
                Dim i As UInt64 = 0
                If t(i) Then
                    results.push_back(mp(True, i))
                    Return True
                Else
                    Return False
                End If
            Else
                results.push_back(mp(False, 0))
                Return True
            End If
        End Function

    Public Function issue() As Boolean
        assert(retrytimes > 0)
        results.clear()
        For i As Int64 = 0 To retrytimes - 1
            If talk.talk() Then
                receiveIndex = 0
                For j As Int64 = 0 To series.size() - 1
                    If Not series(j)() Then
                        Return False
                    End If
                Next
                talk.sendData().clear()
                Return True
            End If
        Next
        Return False
    End Function

    Private Function _result(Of T)(ByVal index As Int64, ByRef rst As Boolean, ByRef d As T, _
                                   ByVal get_data As result_t.DATA_DELEGATE(Of T)) As Boolean
        assert(Not get_data Is Nothing)
        If index >= results.size() Then
            Return False
        Else
            rst = results(index).result()
            d = get_data()
            Return True
        End If
    End Function

    Public Function result(ByVal index As Int64, ByRef rst As Boolean, ByRef d As Object) As Boolean
        Return _result(index, rst, d, AddressOf results(index).data_object)
    End Function

    Public Function result(Of T)(ByVal index As Int64, ByRef rst As Boolean, ByRef d As T) As Boolean
        Return _result(index, rst, d, AddressOf results(index).data(Of T))
    End Function

    Public Function capacity() As Boolean
        Return c(uint64_rtn, protocol.storserver.capacity)
    End Function

    Public Function list() As Boolean
        Dim rtn As _do(Of Boolean) = _
            Function() As Boolean
                If suc() Then
                    Dim i As UInt64 = 0
                    If t(i) Then
                        results.push_back(mp(True, New vector(Of String)()))
                        rb(Of vector(Of String)).size() = i
                        While i > 0
                            Dim s As String = Nothing
                            If t(s) Then
                                rb(Of vector(Of String)).push_back(s)
                            Else
                                Exit While
                            End If
                            dec(i)
                        End While
                        Return i = 0
                    Else
                        Return False
                    End If
                Else
                    results.push_back(mp(False, Nothing))
                    Return True
                End If
            End Function
        Return c(rtn, protocol.storserver.list)
    End Function

    Public Function status() As Boolean
        Dim rtn As _do(Of Boolean) = _
            Function() As Boolean
                If suc() Then
                    Dim i1 As UInt64
                    Dim i2 As UInt64
                    If t(i1) AndAlso t(i2) Then
                        results.push_back(mp(True, make_pair(i1, i2)))
                        Return True
                    Else
                        Return False
                    End If
                Else
                    results.push_back(mp(False, Nothing))
                    Return True
                End If
            End Function
        Return c(rtn, protocol.storserver.status)
    End Function

    Public Function valuesize() As Boolean
        Return c(uint64_rtn, protocol.storserver.valuesize)
    End Function

    Public Function seek(ByVal key As String) As Boolean
        Return c(tf_rtn, protocol.storserver.seek, key)
    End Function

    Public Function read(ByVal key As String) As Boolean
        Dim rtn As _do(Of Boolean) = _
            Function() As Boolean
                If suc() Then
                    Dim buff As bytes = Nothing
                    If t(buff) Then
                        results.push_back(mp(True, buff))
                        Return True
                    Else
                        Return False
                    End If
                Else
                    results.push_back(mp(False, Nothing))
                    Return True
                End If
            End Function
        Return c(rtn, protocol.storserver.read, key)
    End Function

    Private Function wm_rtn() As Boolean
        Return tf_rtn()
    End Function

    Public Function write(ByVal key As String, ByVal buff As bytes) As Boolean
        Return c(AddressOf wm_rtn, protocol.storserver.write, key, buff)
    End Function

    Public Function modify(ByVal key As String, ByVal buff As bytes) As Boolean
        Return c(AddressOf wm_rtn, protocol.storserver.modify, key, buff)
    End Function

    Public Function uniqueWrite(ByVal key As String, ByVal buff As bytes) As Boolean
        Return c(AddressOf wm_rtn, protocol.storserver.uniqueWrite, key, buff)
    End Function

    Public Function open() As Boolean
        Return c(tf_rtn, protocol.storserver.open)
    End Function

    Public Function close() As Boolean
        Return c(tf_rtn, protocol.storserver.close)
    End Function

    Public Function full() As Boolean
        Return c(tf_rtn, protocol.storserver.full)
    End Function

    Public Function health() As Boolean
        Return c(tf_rtn, protocol.storserver.health)
    End Function

    Public Function retire() As Boolean
        Return c(tf_rtn, protocol.storserver.retire)
    End Function

    Public Function empty() As Boolean
        Return c(tf_rtn, protocol.storserver.empty)
    End Function

    Public Function sizeof(ByVal key As String) As Boolean
        Return c(uint64_rtn, protocol.storserver.sizeof, key)
    End Function

    Public Function keycount() As Boolean
        Return c(uint64_rtn, protocol.storserver.keycount)
    End Function

    Public Function sync(ByVal host As String, ByVal port As Int32) As Boolean
        Return c(tf_rtn, protocol.storserver.sync, host, port)
    End Function

    Public Function version() As Boolean
        Dim rtn As _do(Of Boolean) = _
            Function() As Boolean
                Dim s As String = Nothing
                If t(s) Then
                    results.push_back(mp(True, s))
                    Return True
                Else
                    Return False
                End If
            End Function
        Return c(rtn, protocol.storserver.version)
    End Function
End Class
